<template>
  <div class="left-main-wrapper">
    <div v-for="(list, label, listIndex) in diyList" :key="listIndex">
      <div class="padding-xs padding-tb-sm text-16">{{ label }}</div>
      <Draggable :model-value="list" class="components-draggable" item-key="id" :sort="false">
        <template #item="{ element, index }: { element: IDiyBase; index: number }">
          <div
            class="draggable-item"
            ref="dragItemRef"
            @drag="handleDrag"
            @dragstart="
              handleStart({
                item: element,
                index
              })
            "
          >
            <slot name="item" :element="element" :index="index"></slot>
          </div>
        </template>
      </Draggable>
    </div>
  </div>
</template>

<script setup lang="ts">
import Draggable from 'vuedraggable'
import { nextTick, onMounted, type PropType, ref } from 'vue'
import { useDropZone } from '@vueuse/core'
import { cloneDeep } from 'lodash-es'
import type { IDiyBase } from '@/diy/types'
import type { DiyListType } from '@/diy'
import { setPxValue } from '@/utils'

const props = defineProps({
  dragZoneId: {
    type: String,
    required: true
  },
  diyList: {
    type: Object as PropType<DiyListType>,
    required: true
  },
  width: {
    type: Number,
    default: 250
  }
})

const emit = defineEmits(['onEnd', 'onDrag'])

/**
 * 拖动
 */
//是否拖动到放置区域
const dragZoneInfo = ref()
const dragItemRef = ref()
//预览节点信息
const previewEl = ref<HTMLElement | null>(null)
//拖动的子项
const dragItem = ref<IDiyBase | null>(null)
const dragIndex = ref<number>(0)
const handleStart = (params: any) => {
  const { item, index } = params
  dragItem.value = item
  dragIndex.value = index
}
//记录拖拽的位置信息
const position = {
  left: '0',
  top: '0'
}
const handleDrag = (e: any) => {
  //获取拖动位置信息
  const { clientX, clientY } = e
  // 获取拖拽元素的基础信息
  const dragItemRect = dragItemRef.value[dragIndex.value]?.getBoundingClientRect()
  //获取放置区域信息
  const zoneRectInfo = previewEl.value?.getBoundingClientRect()
  const rectX = zoneRectInfo?.x ?? 0
  const rectY = zoneRectInfo?.y ?? 0
  const x = clientX - dragItemRect.width / 2 - rectX
  const y = clientY - dragItemRect.height / 2 - rectY
  const left = x < 0 ? 0 : x
  const top = y < 0 ? 0 : y
  position.left = setPxValue(left)
  position.top = setPxValue(top)
}

//判断是否在放置区域

const onDrop = () => {
  emit('onEnd', {
    position,
    dragItem: cloneDeep(dragItem.value)
  })
}

const handleDragInPreviewZone = () => {
  nextTick(() => {
    const el = document.getElementById(props.dragZoneId)
    previewEl.value = el
    dragZoneInfo.value = useDropZone(el, {
      onDrop
    })
  })
}
onMounted(() => {
  handleDragInPreviewZone()
})
</script>

<style lang="less" scoped>
.left-main-wrapper {
  overflow-x: hidden;
  height: calc(100vh - 64px);
  overflow-y: auto;
  padding: 8px;
  box-sizing: border-box;
}

.components-draggable {
  padding-bottom: 20px;
}

.draggable-item {
  display: inline-block;
  width: 48%;
  margin: 1%;
}
</style>
